// 由一个组件，向上找到最近的指定组件
function findComponentUpward(context, componentName) {
  let parent = context.$parent;
  if (!parent) return
  let name = parent.$options.name;
  while (parent && (!name || [componentName].indexOf(name) < 0)) {
    parent = parent.$parent;
    if (parent) name = parent.$options.name;
  }
  return parent;
}

function findComponentsUpward(context, componentName) {
  let parents = [];
  const parent = context.$parent;
  if (parent) {
    if (parent.$options.name === componentName) parents.push(parent);
    return parents.concat(findComponentsUpward(parent, componentName));
  } else {
    return [];
  }
}

function findComponentsDownward(context, componentName) {
  return context.$children.reduce((components, child) => {
    if (child.$options.name === componentName) components.push(child);
    const foundChilds = findComponentsDownward(child, componentName);
    return components.concat(foundChilds);
  }, []);
}

function typeOf(obj) {
  const toString = Object.prototype.toString
  const map = {
    '[object Number]': 'number',
    '[object String]': 'string',
    '[object Boolean]': 'boolean',
    '[object Array]': 'array',
    '[object Object]': 'object',
    '[object Symbol]': 'symbol',
    '[object Date]': 'date',
    '[object Function]': 'function',
    '[object RegExp]': 'regExp',
    '[object Undefined]': 'undefined',
    '[object Null]': 'null',
  }

  return map[toString.call(obj)]
}

function deepClone(data) {
  const type = typeOf(data)
  let tmp

  if (type === 'array') {
    tmp = []
  } else if (type === 'object') {
    tmp = {}
  } else {
    return data
  }

  if (type === 'array') {
    for (let i = 0; i < data.length; i++) {
      tmp.push(deepClone(data[i]))
    }
  } else if (type === 'object') {
    for (let key in data) {
      tmp[key] = deepClone(data[key])
    }
  }

  return tmp

}

export { findComponentsUpward, findComponentsDownward, findComponentUpward, deepClone }
